const GeneratorAPI = require("./GeneratorAPI");
const logInfo = require('../../util/logInfo');
const logStep = require('../../util/logStep');
const writeFileTree = require("./utils/writeFileTree");

module.exports = class Generator {
  constructor(
    context,
    {
      pkg = {},
      plugins = [],
      completeCbs = [],
      files = {},
      invoking = false,
    } = {}
  ) {
    logStep("4.2 generator-constructor");
    this.files = files;
    this.context = context;
    this.plugins = plugins;
    this.originalPkg = pkg;
    this.pkg = Object.assign({}, pkg);

    const cliService = plugins.find((p) => p.id === "@vue/cli-service");
    const rootOptions = cliService.options;

    logStep("4.2.1 各个插件先执行各自的初始函数-generator");
    logInfo("其中 @vue/cli-service 会构建vue 项目的基础目录和文件模板");
    logInfo("其中 @vue-cli-service 会根据配置构建vue-route/vuex 的文件模板");
    logInfo(
      "其中 @vue/cli-service 会根据配置配置的vue项目的基础依赖比如：sass/style等webpack的基础配置"
    );
    logInfo(
      "@vue-cli-service 会调用 GeneratorAPI 中的 render 函数构建以上内容，存储为实际文件。"
    );
    logInfo(
      "此处 GeneratorAPI 是一个关键的构建输出封装，所有插件的构建操作都会调用这个接口输出文件"
    );
    logInfo('各个插件的用法可以查看 @vue/cli-serve 中的 generator 文件了解详情。')
    plugins.forEach(({ id, apply, options }) => {
      const api = new GeneratorAPI(id, this, options, rootOptions);
      apply(api, options, rootOptions, invoking);
    });
  }

  /**
   * extractConfigFiles/checkExisting 这两个参数是再 add 插件时会传进来，代表已经存在构建文件了
   * 
   */
  async generate({ extractConfigFiles = false, checkExisting = false } = {}) {
    logStep("4.3 generator-generate，再次保存各个配置文件");
    this.files["package.json"] = JSON.stringify(this.pkg, null, 2) + "\n";
    // write/update file tree to disk
    const initialFiles = Object.assign({}, this.files)
    await writeFileTree(this.context, this.files, initialFiles);
  }
};
